/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package org.opprua.tidy.beans;

import java.io.Reader;
import java.io.StringReader;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import com.sun.org.apache.xerces.internal.parsers.SAXParser;

/**
 * TODO: add Java doc
 * 
 * Prepared for first commit: 15.07.2007
 * 
 * @author Lin Li
 */
class BeanXMLSaxParser<T> extends DefaultHandler {

  private BeanXMLPaserElement slave;

  private StringBuffer buf;
  private String field;

  private BeanXMLSaxParser(Class<T> type) {
    slave = BeanXMLPaserElement.createElement(type);
    buf = null;
    field = "";
  }

  /**
   */
  public static <T> T toObject(Class<T> type, String xml) {
    return toObject(type, new StringReader(xml));
  }

  /**
   */
  public static <T> T toObject(Class<T> type, Reader xml) {
    try {
      BeanXMLSaxParser<T> x = new BeanXMLSaxParser<T>(type);

      XMLReader f = new SAXParser();
      f.setFeature("http://xml.org/sax/features/validation", false);
      f.setContentHandler(x);
      f.parse(new InputSource(xml));

      return x.getResult();
    } catch (Exception e) {
      throw new Error("Failed to recreate object from XML", e);
    }
  }

  @SuppressWarnings("unchecked")
  public T getResult() {
    return (T) slave.getData();
  }

  public void characters(char[] data, int start, int stop) {
    if (buf == null) return;
    String d = new String(data, start, stop);
    if (d.trim().length() > 0) {
      buf.append(d);
    }
  }

  public void endElement(String sn, String nn, String n) {
    Object value = null;
    if (buf != null) {
      value = buf.toString();
      buf = null;
    } else if (slave != null) {
      value = slave.getData();
      field = slave.getField();
      slave = slave.getParent();
    }
    slave.addValue(field, value);
  }

  public void startElement(String sn, String nn, String n, Attributes atts) {
    field = atts.getValue("n");
    if ("ab".indexOf(n) > -1) {
      slave = slave.start(field);
    } else if (n.equals("v")) {
      buf = new StringBuffer();
    } else if (n.equals("p")) {
      buf = new StringBuffer();
    } else if (n.equals("null")) {
      buf = null;
    }
  }
}
